﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;
using System.Xml;
using NLog;
using VideoReDo;

namespace VideoReDo
{
   public class VideoReDoAPI
   {
      private static Logger Log = LogManager.GetCurrentClassLogger();

      private VideoReDoSilent _vrds;
      private IVideoReDo _vrd;

      public Boolean Quiet = false;

      public IVideoReDo Interface
      {
         get { return _vrd; }
      }

      public VideoReDoAPI()
      {
         // Instantiate VideoReDo COM object (ie. starts instance of VideoReDo4.exe)
         Log.Debug("Loading VideoReDo COM object...");
         try
         {
            _vrds = new VideoReDoSilent();
         }
         catch (Exception ex)
         {
            Log.ErrorException("Exception instantiating VideoReDoSilent class: " + ex.Message, ex);
            throw ex;
         }

         // Get the programming interface
         Log.Debug("Obtaining VideoReDo programming interface...");
         try
         {
            _vrd = (IVideoReDo)_vrds.VRDInterface;
         }
         catch (Exception ex)
         {
            Log.ErrorException("Exception obtaining VRDInterface: " + ex.Message, ex);
            throw ex;
         }
      }

      public Boolean FileOpen(string filename)
      {
         Log.Debug("Opening file: {0}", filename);

         // Console.WriteLine("  Opening file... ({0})", Path.GetFileName(filename));

         return Interface.FileOpen(filename);
      }

      public Boolean FileClose()
      {
         return Interface.Close();
      }

      public void AdScan()
      {
         Log.Debug("Starting advertisement scan...");

         if (!(Interface.StartAdScan(0, 1, 1)))
            throw new Exception("ERROR:  Unable to start ad scanning.");
      }

      public Boolean AdScan_Block()
      {
         Log.Debug("Scanning file for advertisements...");

         Console.WriteLine("  Scanning for advertisements... (this will take a while)");

         DateTime before = DateTime.Now;

         if (!(Interface.StartAdScan(0, 1, 1)))
            throw new Exception("ERROR:  Unable to start ad scanning.");

         while (Interface.IsScanInProgress())
            Thread.Sleep(100);

         Boolean foundAdvertisements = false;

         if (GetCutListCount() == 0)
         {
            foundAdvertisements = false;
            Console.WriteLine("    Scan finished.  No advertisements found!");
         }
         else
         {
            foundAdvertisements = true;
            Console.WriteLine("    Scan finished.  {0} advertisement(s) found.", GetCutListCount());
         }

         Log.Debug("Scanning finished!");

         return foundAdvertisements;
      }

      public string FileSave(string filename, string profileName)
      {
         return Interface.FileSaveProfile(filename, profileName);
      }

      public string FileSave_Block(string filename, string profileName)
      {
         string result = Interface.FileSaveProfile(filename, profileName);

         while (Interface.IsOutputInProgress())
         {
            Console.Write("\r    Saving File: {0}%", (int)Interface.OutputPercentComplete);

            Thread.Sleep(100);
         }

         Console.WriteLine("\r    Saving File: 100%.  Done!", (int)Interface.OutputPercentComplete);

         return result;
      }

      public Boolean ClearCutList()
      {
         return Interface.ClearCutList();
      }

      public string WriteProjectFile(string filename)
      {
         return Interface.WriteProjectFile(filename);
      }
      /*
      public string GetProgramInfoXML()
      {
         return Interface.GetProgramInfoXML();
      }

      public string GetOutputCompleteInfo()
      {
         return Interface.GetOutputCompleteInfo();
      }
      */
      public double GetProgramDuration()
      {
         return Interface.GetProgramDuration();
      }

      public string GetProfileXML(ushort index)
      {
         return Interface.GetProfileXML(index);
      }

      public string GetProfileXML(string profileName)
      {
         uint profiles = Interface.GetProfilesCount();

         for (ushort i = 1; i <= profiles; i++)
            if (Interface.GetProfileName(i).ToUpper() == profileName.ToUpper())
               return GetProfileXML(i);

         return string.Empty;
      }

      public void DisplayProfiles()
      {
         uint profiles = Interface.GetProfilesCount();

         for (ushort i = 1; i <= profiles; i++)
            Log.Debug("Profile [{0}]: {1}", i, Interface.GetProfileName(i));
      }

      public int GetCutListCount()
      {
         return Interface.GetCutSceneListCount();
      }

      public void DisplayCutList()
      {
         short cuts = Interface.GetCutSceneListCount();

         for (short i = 1; i <= cuts; i++)
            Log.Debug("Cut [{0}]: Start: {1}ms -> {2}ms", i, Interface.GetCutSceneListData(i, 0), Interface.GetCutSceneListData(i, 1));
      }

      public void SaveEDL(string filename)
      {
         Console.WriteLine("    Saving EDL file...");

         if (File.Exists(filename))
            File.Delete(filename);

         short cuts = Interface.GetCutSceneListCount();

         for (short i = 1; i <= cuts; i++)
         {
            int startTime = (int)(Interface.GetCutSceneListData(i, 0) / 1000.0f);
            int endTime = (int)(Interface.GetCutSceneListData(i, 1) / 1000.0f);

            File.AppendAllText(filename, String.Format("{0} {1} 3\n", startTime, endTime));
         }
      }

      public void DisplayFileInformation(string filename)
      {
         if (!(File.Exists(filename)))
         {
            Log.Error("VRD: ERROR: File does not exist: {0}", filename);
            return;
         }

         FileOpen(filename);
         Log.Debug("Filename: {0}", filename);

         double totalSeconds = Interface.GetProgramDuration();
         int hours, minutes, seconds;
         minutes = (int)(totalSeconds / 60);
         hours = (int)(minutes / 60);
         seconds = (int)(totalSeconds % 60);

         Log.Debug("  Duration: {0}:{1}:{2}", hours.ToString("00"), minutes.ToString("00"), seconds.ToString("00"));
         Log.Debug("  Framerate: {0}", Interface.GetFrameRate() / 100.0);

         FileClose();
      }

      public string Version()
      {
         return Interface.VersionNumber;
      }
   }
}
